

#include "stm32f4xx_hal.h"

#include "driv_iic.h"


/* PB8 SCL */
/* PB9 SDA */

#define SCL_PORT    GPIOB
#define SCL_PIN     GPIO_PIN_8

#define SDA_PORT    GPIOB
#define SDA_PIN     GPIO_PIN_9

#define SDA_INPUT_MODE      0
#define SDA_OUTPUT_MODE     1

void IIC_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_SET);
    HAL_GPIO_WritePin(SDA_PORT, SDA_PIN, GPIO_PIN_SET);
    
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    GPIO_InitStruct.Pin = SCL_PIN;
    HAL_GPIO_Init(SCL_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = SDA_PIN;
    HAL_GPIO_Init(SDA_PORT, &GPIO_InitStruct);

}

void WriteSDA(uint32_t level)
{
    if(level > 0)
        HAL_GPIO_WritePin(SDA_PORT, SDA_PIN, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(SDA_PORT, SDA_PIN, GPIO_PIN_RESET);

}

void WriteSCL(uint32_t level)
{
    if(level > 0)
        HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_RESET);
}

void SetSDAMode(uint32_t InputOutupt)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    if(InputOutupt == SDA_OUTPUT_MODE)
    {
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
    }
    else
    {
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
    }

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin = SDA_PIN;
    HAL_GPIO_Init(SDA_PORT, &GPIO_InitStruct);

}

uint32_t ReadSDA(void)
{
    return ((SDA_PORT->IDR & SDA_PIN) != (uint32_t)GPIO_PIN_RESET) ;
}



static void delay_us(uint32_t us)
{
    volatile uint32_t i,j;
    for(i = 0; i < us; i ++)
    {
        for(j = 0; j < 84; j ++)
        {
            j ++;
        }
    }
}




#define AT24C01         127
#define AT24C02         255
#define AT24C04         511
#define AT24C08         1023
#define AT24C16         2047
#define AT24C32         4095
#define AT24C64         8191
#define AT24C128        16383
#define AT24C256        32767  
#define AT24C512        65535

#define EE_TYPE AT24C02



/* IIC_module */

void IIC_Start(void)
{
    SetSDAMode(SDA_OUTPUT_MODE);     
    WriteSDA(1);            
    WriteSCL(1);
    delay_us(4);
    WriteSDA(0);
    delay_us(4);
    WriteSCL(0);
    delay_us(4);
}


void IIC_Stop(void)
{
    SetSDAMode(SDA_OUTPUT_MODE);
    WriteSCL(0);
    WriteSDA(0);
    delay_us(4);
    WriteSCL(1); 
    delay_us(4);
    WriteSDA(1);
    delay_us(4);

}

uint8_t IIC_Wait_Ack(void)
{
    uint16_t ucErrTime=0;
    SetSDAMode(SDA_INPUT_MODE);
    WriteSDA(1);
    delay_us(1);       
    WriteSCL(1);
    delay_us(1);     
    while(ReadSDA())
    {
        ucErrTime++;
        if(ucErrTime>500)
        {
            IIC_Stop();
            return 1;
        }
    }
    WriteSCL(0);
    delay_us(4);

    return 0;  
}


void IIC_Ack(void)
{
    WriteSCL(0);
    SetSDAMode(SDA_OUTPUT_MODE);
    WriteSDA(0);
    delay_us(2);
    WriteSCL(1);
    delay_us(2);
    WriteSCL(0);
    delay_us(4);

}


void IIC_NAck(void)
{
    WriteSCL(0);
    SetSDAMode(SDA_OUTPUT_MODE);
    WriteSDA(1);
    delay_us(2);
    WriteSCL(1);
    delay_us(2);
    WriteSCL(0);
    delay_us(4);

}

      
void IIC_Send_Byte(uint8_t txd)
{
    uint8_t t;   
    SetSDAMode(SDA_OUTPUT_MODE);         
    WriteSCL(0);
    delay_us(2); 

    for(t=0;t<8;t++)
    {              
        WriteSDA((txd>>7)&1);
        txd<<=1;       
        delay_us(2);
        WriteSCL(1);
        delay_us(2); 
        WriteSCL(0);    
        delay_us(2);
    }
    delay_us(2);
    
}

uint8_t IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SetSDAMode(SDA_INPUT_MODE);
    for(i=0;i<8;i++ )
    {
        WriteSCL(0); 
        delay_us(2);
        WriteSCL(1);
        delay_us(2); 
        receive<<=1;
        if(ReadSDA())
            receive++;   
//        delay_us(1); 
    }
    if (!ack)
        IIC_NAck();
    else
        IIC_Ack();
    return receive;
}


/* AT24CXX Module */

void AT24CXX_Init(void)
{
    IIC_GPIO_Init();
    WriteSDA(1);
    WriteSCL(1);
}

uint8_t  AT24CXX_ReadOneByte(uint16_t ReadAddr)
{
    uint8_t  temp=0;                                                                                   
    IIC_Start();  
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);      
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr>>8);
        IIC_Wait_Ack();                 
    }
    else
    {
        IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));  
        IIC_Wait_Ack();
    }
    
    IIC_Send_Byte(ReadAddr&0xff);
    IIC_Wait_Ack();        
    IIC_Start();              
    IIC_Send_Byte(0XA1);          
    IIC_Wait_Ack();     
    temp=IIC_Read_Byte(0);
    IIC_Stop();
    return temp;
}

void AT24CXX_WriteOneByte(uint16_t WriteAddr,uint8_t  DataToWrite)
{
    IIC_Start();  
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);    
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr>>8);
        IIC_Wait_Ack();       
    }
    else
    {
        IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); 
        IIC_Wait_Ack();       
    }
    IIC_Send_Byte(WriteAddr&0xff);  
    IIC_Wait_Ack();                                                           
    IIC_Send_Byte(DataToWrite);
    IIC_Wait_Ack();                     
    IIC_Stop();
    delay_us(1000);     
}


void AT24CXX_WriteLenByte(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t  Len)
{
        uint8_t  t;
        for(t=0;t<Len;t++)
        {
                AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
        }                                                    
}

uint32_t AT24CXX_ReadLenByte(uint16_t ReadAddr,uint8_t  Len)
{
        uint8_t  t;
        uint32_t temp=0;
        for(t=0;t<Len;t++)
        {
            temp<<=8;
            temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                         
        }
        return temp;                                                    
}


uint8_t  AT24CXX_Check(void)
{
    uint8_t  temp;
    temp=AT24CXX_ReadOneByte(0);
    if(temp==0X55)
        return 0;           
    else
    {
        AT24CXX_WriteOneByte(0,0X55);
        temp=AT24CXX_ReadOneByte(0);
        if(temp==0X55)
            return 0;
    }
    return 1;                                              
}

void AT24CXX_Read(uint16_t ReadAddr,uint8_t  *pBuffer,uint16_t NumToRead)
{
    while(NumToRead)
    {
        *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);    
        NumToRead--;
    }
}


void AT24CXX_Write(uint16_t WriteAddr,uint8_t  *pBuffer,uint16_t NumToWrite)
{
    while(NumToWrite--)
    {
        AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
        WriteAddr++;
        pBuffer++;
    }
}


int32_t  AT24Cxx_TestAll(void)
{
    uint16_t i,j;
    uint8_t  temp;

    temp = 0;
    for(j = 0; j < 2048; j ++)
    {
        for(i=0;i<256;i++)
        {
            AT24CXX_WriteOneByte(j,i&0xff);
            temp=AT24CXX_ReadOneByte(j);
            if(temp != (i&0xff))
            {
                return -1;
            }
        }
    }

    return 0;
  
}


int32_t  AT24Cxx_EraseAll(void)
{
    uint16_t j;
    uint8_t  temp;

    for(j = 0; j < 2048; j ++)
    {
        AT24CXX_WriteOneByte(j,0xaa);
        temp=AT24CXX_ReadOneByte(j);
        if(temp != 0xaa)
        {
            return 1;
        }
    }

    return 0;
}

